<template>
  <t-upload ref="uploadRef" @change="onUploadChange" :status="status" :disabled="disabled" :placeholder="placeholder"
    :action="action" :data="uploadData" @success="handleSuccess" :useMockProgress="false"
    :request-method="requestMethod" :theme="theme" :abridgeName="[15, 15]" :accept="accept" :headers="headers"
    :multiple="multiple" :tips="tips" @fail="handleFail" @one-file-fail="onOneFileFail" @remove="onRemove"
    :sizeLimit="{ size: 1024, unit: 'MB', message: '文件大小不能超过1GB' }" v-model="files" :max="max">
    <!-- 实现 slot 透传 -->
    <template v-for="slot in Object.entries(this.$slots)" :slot="slot[0]">
      <slot :name="slot[0]"></slot>
    </template>
  </t-upload>
</template>

<script>
import { VITE_APP_UPLOAD_URL } from '@/api/upload'
import { getToken } from "@/utils/auth";
import { deleteFile } from "@/api/common";
import axios from 'axios';


export default {
  name: "index",
  props: {
    value: [String, Object, Array],
    max: {
      type: Number,
      default: 0,
    },
    placeholder: {
      type: String,
      default: ""
    },
    theme: {
      type: String,
      default: "file"
    },
    tips: {
      type: String,
      default: "" // 文件大小不能超过100MB
    },
    accept: {
      type: String,
      default: '',
    },
    // 文件列表
    fileList: {
      type: Array,
      default: () => [],
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    sizeLimitRange: {
      type: Array,
      default: () => [0, 10485760000]// 1gb
    },
    moduleKey: {
      type: String,
      default: '',
    },
    durationLimit: {
      type: Number,
      default: 0,
    },
    status: {
      type: String,
      default: '',
    },
    action: {
      type: String,
      default: VITE_APP_UPLOAD_URL,
    }
  },
  data () {
    return {
      files: [],
      // action: VITE_APP_UPLOAD_URL,
      headers: {
        Authorization: `Bearer ${getToken()}`,
      },
      uploadData: {
        moduleKey: this.moduleKey,
        videoTime: this.durationLimit
      },
    }
  },
  watch: {
    fileList: {
      handler (val) {
        if (val && val.length > 0) {
          let newArr = val.map(data => {
            return {
              ...data,
              initType: 'init',
            }
          })
          // 防止无限循环，简单比较一下
          if (JSON.stringify(val) !== JSON.stringify(this.files)) {
            this.files = newArr
          }
        } else {
          this.files = [];
        }
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    requestMethod (file) {
      if (Array.isArray(file)) {
        file = file[0]
      }
      // console.log(file, file.raw);
      let formData = new FormData()
      formData.append("file", file.raw)
      formData.append('moduleKey', this.moduleKey);
      formData.append('videoTime', this.durationLimit);
      return new Promise((resolve) => {
        // 限制大小
        if (file.size < this.sizeLimitRange[0] || file.size > this.sizeLimitRange[1]) {
          resolve({ status: 'fail', error: '文件大小不符合' });
          return false;
        }
        let finish = false;
        axios.post(this.action, formData, {
          headers: {
            'Content-Type': 'multipart/form-data;charset=UTF-8',
            'Authorization': `Bearer ${getToken()}`
          },
          onUploadProgress: (progressEvent) => {
            if (progressEvent.lengthComputable) {
              const percent = (((progressEvent.loaded / progressEvent.total) * 100) | 0);
              if (!finish && percent <= 90) {
                this.$refs.uploadRef.uploadFilePercent({ file, percent });
              }
            }
          }
        }).then(res => {
          finish = true;
          const response = res.data;
          if (response.code !== 200) {
            resolve({ status: 'fail', error: response.msg || '上传失败，请重试' });
            return false;
          }
          resolve({ status: 'success', response: { ...response.data, url: response.data.fullFilePath } });
        }).catch((e) => {
          resolve({ status: 'fail', error: e.toString() });
        })
      });
    },
    onUploadChange (value, context) {
      this.$emit('change', value, context);
    },
    formatResponse (res) {
      // 重写 requestMethod 可不用
      // if (res.code !== 200) {
      //   return {error: res.msg || '上传失败，请重试'};
      // }
      // // 限制大小
      // if (res.data.fileSize < this.sizeLimitRange[0] || res.data.fileSize > this.sizeLimitRange[1]) {
      //   return {error: '文件大小不符合'};
      // }
      return { ...res.data, url: res.data.fullFilePath };
    },
    onRemove (context) {
      let file = {}
      if (context.file.response) {
        file = {
          ...context.file,
          ...context.file.response,
        }
      } else {
        file = context.file
      }
      this.resetFiles()
      if (file?.status === 'fail') {
        return false;
      }
      const confirmDia = this.$dialog.confirm({
        header: "文件删除后不可还原",
        body: `是否删除文件名称为"${file.name}"的数据项？`,
        theme: "warning",
        onConfirm: ({ e }) => {
          confirmDia.update({
            confirmBtn: {
              loading: true,
            },
          })
          deleteFile(file.id).then((res) => {
            this.$message.success("删除成功");
            confirmDia.destroy();
          }).catch((e) => {
            this.$message.error(e.toString());
            // 失败返回
            this.files.push(file)
            this.resetFiles();
            confirmDia.destroy();
          });
        },
        onClose: ({ e, trigger }) => {
          this.files.push(file)
          this.resetFiles();
          confirmDia.hide();
        },
      });
    },
    handleFail (obj) {
      this.$message.error(`文件 ${obj.file.name} ${obj.response.error}`);
    },
    onOneFileFail (obj) {
      this.$message.error(`文件 ${obj.file.name} ${obj.response.error}`);
    },
    handleSuccess (context) {
      const ids = []
      this.files.forEach(val => {
        if (val.response) {
          ids.push(val.response.id);
        } else {
          ids.push(val.id)
        }
      });
      this.resetFiles()
      this.$emit("success", ids, this.files);
    },
    // removeFile(file) {
    //   const index = this.files.findIndex(val => file.response.id === val.response.id)
    //   // 是否要真删除文件？
    //   // this.onRemove({
    //   //   file
    //   // })
    //   if (index !== -1) {
    //     this.files.splice(0, 1)
    //     this.resetFiles()
    //   }
    // },
    resetFiles () {
      const ids = []
      this.files.forEach(val => {
        if (val.response) {
          ids.push(val.response.id);
        } else {
          ids.push(val.id)
        }
      });
      this.$emit("update:fileList", this.files);
      this.$emit("input", ids); //  父组件必须设置v-model
    }
  }
}
</script>

<style scoped></style>
